package com.hzit.loan.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hzit.loan.pay.commonApi.enums.PayChannelEnum;
import com.hzit.loan.pay.commonApi.req.RefundReq;
import com.hzit.loan.pay.commonApi.resp.AlipayRefundRespData;
import com.hzit.loan.pay.commonApi.resp.RespVo;
import com.hzit.loan.pay.commonApi.utils.PayDigestUtil;
import com.hzit.loan.pay.config.PayConfig;
import com.hzit.loan.pay.mapper.MchInfoMapper;
import com.hzit.loan.pay.model.MchInfo;
import com.hzit.loan.pay.model.PaySerial;
import com.hzit.loan.pay.model.RefundSerial;
import com.hzit.loan.pay.service.IMcInfoService;
import com.hzit.loan.pay.service.IPaySerialService;
import com.hzit.loan.pay.service.IRefundSerialService;
import com.hzit.loan.pay.service.IRefundService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;

/**
 * 退款相关业务接口实现类
 */
@Service
public class RefundServiceImpl implements IRefundService {


    private Logger logger = LoggerFactory.getLogger(RefundServiceImpl.class);

    @Autowired
    private IMcInfoService mcInfoService;

    @Autowired
    private IRefundSerialService serialService;

    @Autowired
    private IPaySerialService paySerialService;

    @Autowired
    private PayConfig payConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public RespVo doReund(RefundReq refundReq) {

        //签名
        String sign = refundReq.getSign();
        Map map = JSONObject.parseObject(JSONObject.toJSONString(refundReq),Map.class);

       MchInfo mchInfo = mcInfoService.queryMchInfoById(refundReq.getMchId());

       if(ObjectUtils.isEmpty(mchInfo)){
           return RespVo.getFailReturn("商户id不存在");
       }

         String newSign = PayDigestUtil.getSign(map,mchInfo.getReqKey(),"sign");

       if (!sign.equals(newSign)){
           return RespVo.getFailReturn("请求非法");
       }

       //检查流水号是否存在
        PaySerial paySerial = paySerialService.queryByPaySerialNoOrMchOrderNo(refundReq.getPaySerialNo(),refundReq.getMchOrderNo());
        if (ObjectUtils.isEmpty(paySerial)){

            return RespVo.getFailReturn("支付流水号不存在");
        }


        //重复退款 接口幂等，唯一索引，token机制，分布式锁
        List<RefundSerial> refundSerialList = serialService.queryByPaySerialNo(refundReq.getPaySerialNo());


        for (RefundSerial refundSerial :refundSerialList){

            if ("1".equals(refundSerial.getRefundStatus()) || "2".equals(refundSerial.getRefundStatus())){
                return RespVo.getFailReturn("该笔交易存在退款申请，请稍后在试");
            }

        }


        BigDecimal orderAmt = paySerial.getMchOrderAmount(); //100

        BigDecimal refunAmt = new BigDecimal(refundReq.getRefundAmt()); //20 +已经退款成功的记录

        int refundCount = 0;

        for (RefundSerial refundSerial :refundSerialList) {

            if ("0".equals(refundSerial.getRefundStatus())){
                refundCount ++;
                refunAmt = refunAmt.add(refundSerial.getRefundAmount());
            }
        }

        //退款金额是否大于订单金额

        int rlt = refunAmt.compareTo(orderAmt);
        if (rlt<0){
            return RespVo.getFailReturn("退款金额不能超过订单金额");
        }

        //在退款时间内:
        int days = payConfig.getMaxRunfundDay();
        Date paySuccessTime = paySerial.getPaySuccessTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(paySuccessTime);
        calendar.add(Calendar.DAY_OF_MONTH, +days);
        Date finalDate = calendar.getTime();
        Date nowTime = new Date();
        if (nowTime.after(finalDate)){
            return RespVo.getFailReturn("已经超过退款期限");
        }

        //是否超过50比退款
        if(refundCount >=50){
            return RespVo.getFailReturn("单笔交易最多支持50次退款");
        }

        //生成-退款申请中的流水
        RefundSerial refundSerial = serialService.createRefundSerial(refundReq,paySerial);

        //根据 payChannel 调用不同的前置服务
        if(PayChannelEnum.ALIPAY.getCode().equals(paySerial.getPayChannel())){
            String url = "http://ALIAPT-FRONT/alipayFront/refund";

            HashMap hashMap = new HashMap();
            hashMap.put("refundSerialNo",refundSerial.getRefundSerialNo());
            hashMap.put("paySeiralNo",refundSerial.getOriPaySerialNo());
            hashMap.put("refundAmt",refundSerial.getRefundAmount());
            hashMap.put("refundReason",refundSerial.getRefundReason());

            RespVo<AlipayRefundRespData>  respVo = restTemplate.getForObject(url,RespVo.class,hashMap);

            if(0 != respVo.getCode()){
                return RespVo.getFailReturn("退款失败");
            }

            AlipayRefundRespData alipayRefundRespData = respVo.getData();

            if(!alipayRefundRespData.isSuccess){
                return RespVo.getFailReturn(alipayRefundRespData.getDesc());
            }

            //TODO 更新数据库
            serialService.updateRefundSerial();

            respVo.setCode(0);
            respVo.setMsg("退款成功");
            return respVo;

        } else if(PayChannelEnum.WECHAT.getCode().equals(paySerial.getPayChannel())){
            // 调用微信前置服务，1.调用前置服务
            //2.返回对象
            //3.更新流水为银行处理中

            //3.1 如果是零钱支付的，我就把消息放到延时队列

            //4.封装对象返回，银行受理，3个工作日到你银行卡

        }else if("icbc".equals(paySerial.getPayChannel())){
            //工行退款，批量
            //插入退款中的流水
            //封装对象返回，返回状态退款受理中

        }

        // 更新表状态

        // 封装对象返回

        return null;

    }
}
